gusucode.com > 各种VC自绘控件源码程序 > 各种VC自绘控件源码/code/SkinControls(自绘MFC基本控件 )/SkinControls/SkinControls/SkinScrollBar.cpp
#include "stdafx.h" #include "internal.h" #include "SkinScrollBar.h" #include <assert.h> static TCHAR g_szPropSB[] = TEXT("SkinScrollBar"); const int SBMETRICS::cxVArrow = 16;//GetSystemMetrics(SM_CXVSCROLL); const int SBMETRICS::cyVArrow = 16;//GetSystemMetrics(SM_CYVSCROLL); const int SBMETRICS::cxHArrow = 16;//GetSystemMetrics(SM_CXHSCROLL); const int SBMETRICS::cyHArrow = 16;//GetSystemMetrics(SM_CYHSCROLL); const int SBMETRICS::cxThumb = 16;//GetSystemMetrics(SM_CXHTHUMB); const int SBMETRICS::cyThumb = 16;//GetSystemMetrics(SM_CYVTHUMB); // Public interfaces //---------------------------------------------------------- // Name : SkinSB_Init() // Desc : Initialize the skin scrollbar library //---------------------------------------------------------- BOOL WINAPI SkinSB_InitH(HWND hwnd, HBITMAP hBmp) { LPSKINSB psb; DWORD dwStyle; if( !IsWindow(hwnd) ) { SetLastError(ERROR_INVALID_HANDLE); return FALSE; } if( SkinSB_IsValid(hwnd) ) return FALSE; // Allocates memory psb = (LPSKINSB)LocalAlloc(LPTR, sizeof(SKINSB)); if( psb == NULL ) return FALSE; ZeroMemory(psb, sizeof(SKINSB)); dwStyle = GetWindowLong(hwnd, GWL_STYLE); psb->Horz.cbSize = psb->Vert.cbSize = sizeof(SCROLLINFO); psb->Horz.fMask = psb->Vert.fMask = SIF_ALL|SIF_DISABLENOSCROLL; if( dwStyle & WS_HSCROLL ) GetScrollInfo(hwnd, SB_HORZ, &psb->Horz); if( dwStyle & WS_VSCROLL ) GetScrollInfo(hwnd, SB_VERT, &psb->Vert); // Is left scrollbar style if( GetWindowLong(hwnd, GWL_EXSTYLE) & WS_EX_LEFTSCROLLBAR ) psb->fLeftScrollBar = TRUE; if( !hBmp ) { SetLastError(ERROR_INVALID_HANDLE); return FALSE; } psb->hBmp = hBmp; // Replace the window procedure psb->hwnd = hwnd; psb->pfnOldProc = (WNDPROC)(LONG_PTR)SetWindowLong(hwnd, GWL_WNDPROC, (LONG)(LONG_PTR)SkinSB_Proc); psb->fPreventStyleChange = FALSE; psb->fTracking = FALSE; // Whether richedit control TCHAR szClassName[255] = { 0 }; GetClassName(hwnd, szClassName, sizeof(szClassName)); if( _strcmpi(szClassName, TEXT("RichEdit20A")) == 0 || _strcmpi(szClassName, TEXT("RichEdit20W")) == 0 ) { psb->fRichEdit = TRUE; } // Set the window property if( !SetProp(hwnd, g_szPropSB, (HANDLE)psb) ) return FALSE; // Redraw the window noclient RedrawFrame(hwnd); return TRUE; } //---------------------------------------------------------------- // Name : SkinSB_Init() // Desc : Initialize and load the scrollbar skin //---------------------------------------------------------------- BOOL WINAPI SkinSB_Init(HWND hwnd, LPCTSTR pszFileName) { LPSKINSB psb; DWORD dwStyle; if( !IsWindow(hwnd) ) { SetLastError(ERROR_INVALID_HANDLE); return FALSE; } if( SkinSB_IsValid(hwnd) ) return FALSE; // Allocates memory psb = (LPSKINSB)LocalAlloc(LPTR, sizeof(SKINSB)); if( psb == NULL ) return FALSE; ZeroMemory(psb, sizeof(SKINSB)); dwStyle = GetWindowLong(hwnd, GWL_STYLE); psb->Horz.cbSize = psb->Vert.cbSize = sizeof(SCROLLINFO); psb->Horz.fMask = psb->Vert.fMask = SIF_ALL|SIF_DISABLENOSCROLL; if( dwStyle & WS_HSCROLL ) GetScrollInfo(hwnd, SB_HORZ, &psb->Horz); if( dwStyle & WS_VSCROLL ) GetScrollInfo(hwnd, SB_VERT, &psb->Vert); // Is left scrollbar style if( GetWindowLong(hwnd, GWL_EXSTYLE) & WS_EX_LEFTSCROLLBAR ) psb->fLeftScrollBar = TRUE; if (pszFileName == NULL) return FALSE; HBITMAP hBmp = (HBITMAP)::LoadImage(AfxGetInstanceHandle(), pszFileName, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE|LR_CREATEDIBSECTION); psb->hBmp = hBmp; // Replace the window procedure psb->hwnd = hwnd; psb->pfnOldProc = (WNDPROC)(LONG_PTR)SetWindowLong(hwnd, GWL_WNDPROC, (LONG)(LONG_PTR)SkinSB_Proc); psb->fPreventStyleChange = FALSE; psb->fTracking = FALSE; // Whether richedit control TCHAR szClassName[255] = { 0 }; GetClassName(hwnd, szClassName, sizeof(szClassName)); if( _strcmpi(szClassName, TEXT("RichEdit20A")) == 0 || _strcmpi(szClassName, TEXT("RichEdit20W")) == 0 ) { psb->fRichEdit = TRUE; } // Set the window property if( !SetProp(hwnd, g_szPropSB, (HANDLE)psb) ) return FALSE; // Redraw the window noclient RedrawFrame(hwnd); return TRUE; } //--------------------------------------------------------- // Name : SkinSB_Uninit() // Desc : Finalize the skin scrollbar library //--------------------------------------------------------- BOOL WINAPI SkinSB_Uninit(HWND hwnd) { LPSKINSB psb; SCROLLINFO vsi; SCROLLINFO hsi; BOOL vValid, hValid; UINT vFlags, hFlags; if( (psb = SkinSB_GetSB(hwnd)) == NULL ) return FALSE; vsi.cbSize = hsi.cbSize = sizeof(SCROLLINFO); vsi.fMask = hsi.fMask = SIF_ALL | SIF_DISABLENOSCROLL; vValid = SkinSB_GetScrollInfo(hwnd, SB_VERT, &vsi); vFlags = SkinSB_GetDisableFlags(psb, TRUE); hValid = SkinSB_GetScrollInfo(hwnd, SB_HORZ, &hsi); hFlags = SkinSB_GetDisableFlags(psb, FALSE); // Remove the subclass procedure SetWindowLong(hwnd, GWL_WNDPROC, (LONG)(LONG_PTR)psb->pfnOldProc); RemoveProp(hwnd, g_szPropSB); LocalFree((HLOCAL)psb); // Restore system scroll parameters if( vValid ) { SetScrollInfo(hwnd, SB_VERT, &vsi, TRUE); EnableScrollBar(hwnd, SB_VERT, vFlags); } if( hValid ) { SetScrollInfo(hwnd, SB_HORZ, &hsi, TRUE); EnableScrollBar(hwnd, SB_HORZ, hFlags); } return TRUE; } //--------------------------------------------------------- // Name : SkinSB_IsValid() // Desc : Is initialized ?? //--------------------------------------------------------- BOOL WINAPI SkinSB_IsValid(HWND hwnd) { return (SkinSB_GetSB(hwnd) != NULL); } //--------------------------------------------------------- // Name : SkinSB_GetScrollInfo() // Desc : Overload API GetScrollInfo() //--------------------------------------------------------- BOOL WINAPI SkinSB_GetScrollInfo(HWND hwnd, int fnBar, LPSCROLLINFO lpsi) { if( !lpsi || lpsi->cbSize != sizeof(SCROLLINFO) ) return FALSE; LPSKINSB psb; LPSCROLLINFO psi = NULL; BOOL fCopied = FALSE; // Is initialized ? if( (psb = SkinSB_GetSB(hwnd)) == NULL ) return FALSE; // If be scrollbar control then call failed if( fnBar == SB_HORZ ) psi = &psb->Horz; else if( fnBar == SB_VERT ) psi = &psb->Vert; else if( fnBar == SB_CTL ) return FALSE; if( lpsi->fMask & SIF_PAGE ) { lpsi->nPage = psi->nPage; fCopied = TRUE; } if( lpsi->fMask & SIF_POS ) { lpsi->nPos = psi->nPos; fCopied = TRUE; } if( lpsi->fMask & SIF_TRACKPOS ) { lpsi->nTrackPos = psi->nTrackPos; fCopied = TRUE; } if( lpsi->fMask & SIF_RANGE ) { lpsi->nMin = psi->nMin; lpsi->nMax = psi->nMax; fCopied = TRUE; } return fCopied; } //--------------------------------------------------------- // Name : SkinSB_SetScrollInfo() // Desc : Overload API SetScrollInfo() //--------------------------------------------------------- int WINAPI SkinSB_SetScrollInfo(HWND hwnd, int fnBar, LPCSCROLLINFO psi, BOOL fRedraw) { LPSKINSB psb; LPSCROLLINFO mysi; int nRet; DWORD dwStyle; BOOL fVert; UINT wScroll; BOOL fScroll; BOOL fOldScroll; BOOL bReturnOldPos; // if be scrollbar control the call failed if( fnBar == SB_CTL ) return 0; if( (psb = SkinSB_GetSB(hwnd)) == NULL ) return 0; if( fRedraw ) fRedraw = IsWindowVisible(hwnd); fVert = (fnBar == SB_VERT); bReturnOldPos = (psi->fMask & SIF_POS); dwStyle = GetWindowLong(hwnd, GWL_STYLE); wScroll = fVert ? WS_VSCROLL : WS_HSCROLL; fScroll = fOldScroll = (dwStyle & wScroll) ? TRUE : FALSE; // Don't do anything if we're setting position of a nonexistent scroll bar. if( !(psi->fMask & SIF_RANGE) && !fOldScroll ) return 0; mysi = (fVert ? &psb->Vert : &psb->Horz); if( !SkinSB_SetSBParms(mysi, *psi, &fScroll, &nRet, bReturnOldPos) && !(psi->fMask & SIF_DISABLENOSCROLL) ) { if( fOldScroll && fRedraw ) goto redrawAfterSet; return nRet; } if( fScroll ) { psb->style |= wScroll; dwStyle |= wScroll; } else { psb->style &= ~wScroll; dwStyle &= ~wScroll; } // Keep the owner window scroll style SetWindowLong(hwnd, GWL_STYLE, dwStyle); if( psi->fMask & SIF_DISABLENOSCROLL ) { if( fOldScroll ) { fScroll = ((int)mysi->nPage <= (mysi->nMax - mysi->nMin)); psb->style |= wScroll; dwStyle |= wScroll; SetWindowLong(hwnd, GWL_STYLE, dwStyle); SkinSB_EnableArrows(psb, fnBar, fScroll ? ESB_ENABLE_BOTH : ESB_DISABLE_BOTH); } } else if( fOldScroll ^ fScroll ) { RedrawFrame(hwnd); return nRet; } if( fScroll && fRedraw ) { redrawAfterSet: if(dwStyle & wScroll) { HDC hDC = GetWindowDC(hwnd); SkinSB_DrawThumb(psb, hDC, fVert, SkinSB_GetState(psb, fVert, HTSCROLL_THUMB)); ReleaseDC(hwnd, hDC); } else { if( SkinSB_IsScrollInfoActive(psi) ) RedrawFrame(hwnd); } } return mysi->nPos; //lres; } //--------------------------------------------------------- // Name : SkinSB_GetScrollPos() // Desc : Overload API GetScrollPos() //--------------------------------------------------------- int WINAPI SkinSB_GetScrollPos(HWND hwnd, int nBar) { LPSKINSB psb; int nPos; if( !(psb = SkinSB_GetSB(hwnd)) ) return FALSE; if( nBar == SB_HORZ ) nPos = psb->Horz.nPos; else if( nBar == SB_VERT ) nPos = psb->Vert.nPos; else nPos = 0; return nPos; } //--------------------------------------------------------- // Name : SkinSB_SetScrollPos() // Desc : Overload API SetScrollPos() //--------------------------------------------------------- int WINAPI SkinSB_SetScrollPos(HWND hwnd, int nBar, int nPos, BOOL fRedraw) { LPSKINSB psb; LPSCROLLINFO psi; int nOldPos; if( (psb = SkinSB_GetSB(hwnd)) == NULL) return FALSE; if( nBar == SB_HORZ ) psi = &psb->Horz; else if( nBar == SB_VERT ) psi = &psb->Vert; else return FALSE; nOldPos = psi->nPos; psi->nPos = nPos; if( fRedraw ) { HDC hDC = GetWindowDC(hwnd); SkinSB_DrawScrollBar(psb, hDC, (nBar == SB_VERT) ); ReleaseDC(hwnd, hDC); } return nOldPos; } //--------------------------------------------------------- // Name : SkinSB_GetScrollRange() // Desc : Overload API GetScrollRange() //--------------------------------------------------------- BOOL WINAPI SkinSB_GetScrollRange(HWND hwnd, int nBar, LPINT lpMinPos, LPINT lpMaxPos) { LPSKINSB psb; LPSCROLLINFO psi; if( !lpMinPos || !lpMaxPos ) return FALSE; if( nBar == SB_CTL ) return FALSE; if( (psb = SkinSB_GetSB(hwnd)) == NULL ) return FALSE; if( nBar == SB_HORZ ) psi = &psb->Horz; else if( nBar == SB_VERT ) psi = &psb->Vert; else return FALSE; *lpMinPos = psi->nMin; *lpMaxPos = psi->nMax; return TRUE; } //--------------------------------------------------------- // Name : SkinSB_SetScrollRange() // Desc : Overload API SetScrollRange() //--------------------------------------------------------- BOOL WINAPI SkinSB_SetScrollRange(HWND hwnd, int nBar, int nMinPos, int nMaxPos, BOOL fRedraw) { LPSKINSB psb; LPSCROLLINFO psi; if( !(psb = SkinSB_GetSB(hwnd)) ) return FALSE; if( nBar == SB_HORZ ) psi = &psb->Horz; else if( nBar == SB_VERT ) psi = &psb->Vert; else return FALSE; psi->nMin = nMinPos; psi->nMax = nMaxPos; if(nMinPos == 0 && nMaxPos == 0) SkinSB_ShowScrollBar(hwnd, nBar, FALSE); if( fRedraw ) { HDC hDC = GetWindowDC(hwnd); SkinSB_DrawScrollBar(psb, hDC, (nBar == SB_VERT) ); ReleaseDC(hwnd, hDC); } return TRUE; } //--------------------------------------------------------- // Name : SkinSB_ShowScrollBar() // Desc : Overload API ShowScrollBar() //--------------------------------------------------------- BOOL WINAPI SkinSB_ShowScrollBar(HWND hwnd, int wBar, BOOL fShow) { BOOL fChanged = FALSE; DWORD dwStyle, dwNew = 0; switch( wBar ) { case SB_CTL: ShowWindow(hwnd, fShow ? SW_SHOW : SW_HIDE); break; case SB_HORZ: dwNew = WS_HSCROLL; break; case SB_VERT: dwNew = WS_VSCROLL; break; case SB_BOTH: dwNew = WS_HSCROLL | WS_VSCROLL; break; } dwStyle = GetWindowLong(hwnd, GWL_STYLE); if( !fShow ) { if( dwStyle & dwNew ) { fChanged = TRUE; dwStyle &= ~dwNew; } } else { if( (dwStyle & dwNew) != dwNew ) { fChanged = TRUE; dwStyle |= dwNew; } } if( fChanged ) { SetWindowLong(hwnd, GWL_STYLE, dwStyle); RedrawFrame(hwnd); } return TRUE; } //--------------------------------------------------------- // Name : SkinSB_EnableScrollBar() // Desc : Overload API EnableScrollBar() //--------------------------------------------------------- BOOL WINAPI SkinSB_EnableScrollBar(HWND hwnd, UINT wSBflags, UINT wArrows) { LPSKINSB psb; if( !(psb = SkinSB_GetSB(hwnd)) ) return FALSE; if( wSBflags == SB_CTL ) return FALSE; return SkinSB_EnableArrows(psb, wSBflags, wArrows); } // Internal Function //--------------------------------------------------------- // Name : SkinSB_SetSBParms() // Desc : Set scroll parameters //--------------------------------------------------------- BOOL SkinSB_SetSBParms(LPSCROLLINFO psi, SCROLLINFO si, BOOL* pfScroll, int* plres, BOOL bOldPos) { BOOL fChanged = FALSE; if( bOldPos ) *plres = psi->nPos; if( si.fMask & SIF_RANGE ) { if( si.nMax < si.nMin ) si.nMax = si.nMin; if( si.nMax != psi->nMax || si.nMin != psi->nMin ) { psi->nMax = si.nMax; psi->nMin = si.nMin; if( !(si.fMask & SIF_PAGE) ) { si.fMask |= SIF_PAGE; si.nPage = psi->nPage; } if( !(si.fMask & SIF_POS) ) { si.fMask |= SIF_POS; si.nPos = psi->nPos; } fChanged = TRUE; } } if( si.fMask & SIF_PAGE ) { UINT nMaxPage = abs( psi->nMax - psi->nMin ) + 1; if( si.nPage > nMaxPage ) si.nPage = nMaxPage; if( psi->nPage != si.nPage ) { psi->nPage = si.nPage; if( !(si.fMask & SIF_POS) ) { si.fMask |= SIF_POS; si.nPos = psi->nPos; } fChanged = TRUE; } } if( si.fMask & SIF_POS ) { int nMaxPos = psi->nMax - ((psi->nPage) ? psi->nPage - 1 : 0); if( si.nPos < psi->nMin ) si.nPos = psi->nMin; else if( si.nPos > nMaxPos ) si.nPos = nMaxPos; if( psi->nPos != si.nPos ) { psi->nPos = si.nPos; fChanged = TRUE; } } if( si.fMask & SIF_TRACKPOS ) { if( psi->nTrackPos != si.nTrackPos ) { psi->nTrackPos = si.nTrackPos; fChanged = TRUE; } } if( !bOldPos ) *plres = psi->nPos; // Return the new pos if( si.fMask & SIF_RANGE ) { if( *pfScroll = (psi->nMin != psi->nMax) ) goto CheckPage; } else if( si.fMask & SIF_PAGE ) { CheckPage: *pfScroll = ( (int)psi->nPage <= (psi->nMax - psi->nMin) ); } return fChanged; } //--------------------------------------------------------- // Name : SkinSB_EnableArrows() // Desc : Enable or Disable scrollbar arrows //--------------------------------------------------------- BOOL SkinSB_EnableArrows(LPSKINSB psb, int nBar, UINT wArrows) { HDC hDC; UINT uOldFlags; BOOL bRetValue = FALSE; if( psb == NULL ) return FALSE; uOldFlags = psb->flags; if( (hDC = GetWindowDC(psb->hwnd)) == NULL ) return FALSE; // Enable or disable horizontal scrollbar if( nBar == SB_HORZ || nBar == SB_BOTH ) { if( wArrows == ESB_ENABLE_BOTH ) psb->flags &= ~ESB_DISABLE_BOTH; else psb->flags |= wArrows; if( uOldFlags != psb->flags ) { bRetValue = TRUE; if( GetWindowLong(psb->hwnd, GWL_STYLE ) & WS_HSCROLL ) SkinSB_DrawScrollBar(psb, hDC, FALSE); } } // Enable or disable vertical scrollbar if( nBar == SB_VERT || nBar == SB_BOTH ) { if( wArrows == ESB_ENABLE_BOTH ) psb->flags &= ~(ESB_DISABLE_BOTH << 2); else psb->flags |= (wArrows << 2); if( uOldFlags != psb->flags ) { bRetValue = TRUE; if( GetWindowLong(psb->hwnd, GWL_STYLE ) & WS_VSCROLL ) SkinSB_DrawScrollBar(psb, hDC, TRUE); } } ReleaseDC(psb->hwnd, hDC); return bRetValue; } //--------------------------------------------------------- // Name : SkinSB_GetDisableFlags() // Desc : Get scrollbar disable flags //--------------------------------------------------------- UINT SkinSB_GetDisableFlags(LPSKINSB psb, BOOL fVert) { return (fVert ? (psb->flags & 0x000c) >> 2 : psb->flags & 0x0003); } //--------------------------------------------------------- // Name : SkinSB_SetWindowBits() // Desc : //--------------------------------------------------------- void SkinSB_SetWindowBits(HWND hWnd, int iWhich, DWORD dwBits, DWORD dwValue) { DWORD dwStyle; DWORD dwNewStyle; dwStyle = GetWindowLong(hWnd, iWhich); dwNewStyle = ( dwStyle & ~dwBits ) | (dwValue & dwBits); if (dwStyle != dwNewStyle) { SetWindowLong(hWnd, iWhich, dwNewStyle); } } //--------------------------------------------------------- // Name : SkinSB_GetSB() // Desc : Get the skin scrollbar data structure //--------------------------------------------------------- LPSKINSB SkinSB_GetSB(HWND hwnd) { return (LPSKINSB)GetProp(hwnd, g_szPropSB); } //--------------------------------------------------------- // Name : SkinSB_IsScrollInfoActive() // Desc : Check scroll information whether active //--------------------------------------------------------- BOOL SkinSB_IsScrollInfoActive(LPCSCROLLINFO lpsi) { if( (lpsi->nPage <= 0) || (lpsi->nMax <= lpsi->nMin) ) return FALSE; else return TRUE; //TCHAR szText[255]={0}; //sprintf_s(szText, sizeof(szText), "Page=%d Max=%d Min=%d Pos=%d\n", lpsi->nPage, lpsi->nMax, lpsi->nMin, lpsi->nPos); //OutputDebugString(szText); //return lpsi->nPage > 0 ? TRUE : FALSE; } //---------------------------------------------------------- // Name : SkinSB_GetSizeBoxRect() // Desc : Get the size box rect //---------------------------------------------------------- BOOL SkinSB_GetSizeBoxRect(LPSKINSB psb, LPRECT lprc) { DWORD dwStyle; RECT rect; SetRectEmpty(lprc); dwStyle = GetWindowLong(psb->hwnd, GWL_STYLE); if( (dwStyle & WS_HSCROLL) && (dwStyle & WS_VSCROLL) ) { GetClientRect(psb->hwnd, &rect); ClientToScreen(psb->hwnd, (LPPOINT)&rect); ClientToScreen(psb->hwnd, ((LPPOINT)&rect)+1); // calculate rect of left scrollbar sizebox if( psb->fLeftScrollBar ) { lprc->left = rect.left - SBMETRICS::cxVArrow; lprc->right = rect.left; } else { lprc->left = rect.right; lprc->right = rect.right + SBMETRICS::cxVArrow; } lprc->top = rect.bottom; lprc->bottom = rect.bottom + SBMETRICS::cxHArrow; return TRUE; } return FALSE; } //---------------------------------------------------------- // Name : SkinSB_GetScrollBarRect() // Desc : Get the scrollbar rect //---------------------------------------------------------- BOOL SkinSB_GetScrollBarRect(LPSKINSB psb, BOOL fVert, LPRECT lprc) { assert(psb && lprc); if( !psb || !lprc ) return FALSE; RECT rect; DWORD dwStyle; SetRectEmpty(lprc); GetClientRect(psb->hwnd, &rect); ClientToScreen(psb->hwnd, (LPPOINT)&rect); ClientToScreen(psb->hwnd, ((LPPOINT)&rect)+1); dwStyle = GetWindowLong(psb->hwnd, GWL_STYLE); if( fVert ) { if( psb->fLeftScrollBar ) { lprc->right = lprc->left = rect.left; if( dwStyle & WS_VSCROLL ) lprc->left -= SBMETRICS::cxThumb; } else { lprc->right = lprc->left = rect.right; if( dwStyle & WS_VSCROLL ) lprc->right += SBMETRICS::cxThumb; } lprc->top = rect.top; lprc->bottom = rect.bottom; } else { lprc->top = lprc->bottom = rect.bottom; if( dwStyle & WS_HSCROLL ) lprc->bottom += SBMETRICS::cyThumb; lprc->left = rect.left; lprc->right = rect.right; } return TRUE; } //---------------------------------------------------------- // Name : SkinSB_GetThumbRect() // Desc : //---------------------------------------------------------- BOOL SkinSB_GetThumbRect(LPSKINSB psb, LPRECT lprc, BOOL fVert) { assert(psb && lprc); if( !psb || !lprc ) return FALSE; SBCALC sbc; RECT rect; SkinSB_SBCalc(psb, &sbc, fVert); GetWindowRect(psb->hwnd, &rect); if( fVert ) SetRect(lprc, sbc.pxLeft, sbc.pxThumbTop, sbc.pxRight, sbc.pxThumbBottom); else SetRect(lprc, sbc.pxThumbLeft, sbc.pxTop, sbc.pxThumbRight, sbc.pxBottom); OffsetRect(lprc, -rect.left, -rect.top); return TRUE; } //---------------------------------------------------------- // Name : SkinSB_GetGrooveRect() // Desc : //---------------------------------------------------------- BOOL SkinSB_GetGrooveRect(LPSKINSB psb, LPRECT lprc, BOOL fVert) { assert(psb && lprc); if( !psb || !lprc ) return FALSE; SBCALC sbc; RECT rect; SkinSB_SBCalc(psb, &sbc, fVert); GetWindowRect(psb->hwnd, &rect); if( fVert ) SetRect(lprc, sbc.pxLeft, sbc.pxUpArrow, sbc.pxRight, sbc.pxDownArrow); else SetRect(lprc, sbc.pxUpArrow, sbc.pxTop, sbc.pxDownArrow, sbc.pxBottom); OffsetRect(lprc, -rect.left, -rect.top); return TRUE; } //---------------------------------------------------------- // Name : SkinSB_DrawSizeBox() // Desc : Draw the size box //---------------------------------------------------------- BOOL SkinSB_DrawSizeBox(LPSKINSB psb, HDC hdc) { HDC hMemDC; HBITMAP hOldBmp; RECT rect, rc; GetWindowRect(psb->hwnd, &rect); SkinSB_GetSizeBoxRect(psb, &rc); OffsetRect(&rc, -rect.left, -rect.top); hMemDC = CreateCompatibleDC(NULL); hOldBmp = (HBITMAP)SelectObject(hMemDC, psb->hBmp); BitBlt(hdc, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, hMemDC, (psb->fLeftScrollBar ? 16 : 0), 16 * 2, SRCCOPY); // Release GDI object SelectObject(hMemDC, hOldBmp); DeleteDC(hMemDC); return TRUE; } //---------------------------------------------------------- // Name : SkinSB_DrawGroove() // Desc : //---------------------------------------------------------- BOOL SkinSB_DrawGroove(LPSKINSB psb, HDC hdc, LPRECT lprc, BOOL fVert) { if( !hdc || !lprc || IsRectEmpty(lprc) ) return FALSE; HDC hbmpDC; HBITMAP hOldBmp; int nMode; hbmpDC = CreateCompatibleDC(hdc); hOldBmp = (HBITMAP)SelectObject(hbmpDC, psb->hBmp); nMode = SetStretchBltMode(hdc, HALFTONE); StretchBlt(hdc, lprc->left, lprc->top, lprc->right - lprc->left, lprc->bottom - lprc->top, hbmpDC, 16 * 14, (fVert ? 0 : 16), 16, 16, SRCCOPY); SetStretchBltMode(hdc, nMode); SelectObject(hbmpDC, hOldBmp); DeleteDC(hbmpDC); return TRUE; } //---------------------------------------------------------- // Name : SkinSB_DrawScrollBar() // Desc : Draw the scrollbar //---------------------------------------------------------- void SkinSB_DrawScrollBar(LPSKINSB psb, HDC hdc, BOOL fVert) { RECT rcGroove; RECT rcThumb; int nSaveDC = 0; SkinSB_GetGrooveRect(psb, &rcGroove, fVert); SkinSB_GetThumbRect(psb, &rcThumb, fVert); if( (rcThumb.right > rcThumb.left) && (rcThumb.bottom > rcThumb.top) && SkinSB_IsScrollInfoActive((fVert ? &psb->Vert : &psb->Horz))) { // Draw the thumb SkinSB_DrawThumb(psb, hdc, fVert, SkinSB_GetState(psb, fVert, HTSCROLL_THUMB)); nSaveDC = SaveDC(hdc); ExcludeClipRect(hdc, rcThumb.left, rcThumb.top, rcThumb.right, rcThumb.bottom); } SkinSB_DrawGroove(psb, hdc, &rcGroove, fVert); if( nSaveDC != 0 ) RestoreDC(hdc, nSaveDC); // Draw the arrow SkinSB_DrawArrow(psb, hdc, fVert, HTSCROLL_LINEUP, SkinSB_GetState(psb, fVert, HTSCROLL_LINEUP) ); SkinSB_DrawArrow(psb, hdc, fVert, HTSCROLL_LINEDOWN, SkinSB_GetState(psb, fVert, HTSCROLL_LINEDOWN)); } //---------------------------------------------------------- // Name : SkinSB_DrawArrow() // Desc : Draw the scrollbar arrow button //---------------------------------------------------------- BOOL SkinSB_DrawArrow(LPSKINSB psb, HDC hdc, BOOL fVert, int nArrow, UINT uState) { RECT rect, rc; SBCALC sbc; HDC hMemDC; HBITMAP hOldBmp; int xOffset = 0, yOffset = 0; GetWindowRect(psb->hwnd, &rect); SkinSB_SBCalc(psb, &sbc, fVert); if( uState == 0 ) uState = SkinSB_GetState(psb, fVert, nArrow); hMemDC = CreateCompatibleDC(hdc); hOldBmp = (HBITMAP)SelectObject(hMemDC, psb->hBmp); switch( nArrow ) { // up or left arrow case HTSCROLL_LINEUP: if( fVert ) { xOffset = 16 * uState; yOffset = 0; SetRect(&rc, sbc.pxLeft, sbc.pxTop, sbc.pxRight, sbc.pxUpArrow); } else { xOffset = 16 * uState; yOffset = 16; SetRect(&rc, sbc.pxLeft, sbc.pxTop, sbc.pxUpArrow, sbc.pxBottom); } break; // right or down arrow case HTSCROLL_LINEDOWN: if( fVert ) { xOffset = 16 * (uState + 4); yOffset = 0; SetRect(&rc, sbc.pxLeft, sbc.pxDownArrow, sbc.pxRight, sbc.pxBottom); } else { xOffset = 16 * (uState + 4); yOffset = 16; SetRect(&rc, sbc.pxDownArrow, sbc.pxTop, sbc.pxRight, sbc.pxBottom); } break; default: assert(0); } OffsetRect(&rc, -rect.left, -rect.top); BitBlt(hdc, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, hMemDC, xOffset, yOffset, SRCCOPY); SelectObject(hMemDC, hOldBmp); DeleteDC(hMemDC); return TRUE; } //---------------------------------------------------------- // Name : SkinSB_DrawThumb() // Desc : Draw the thumb //---------------------------------------------------------- void SkinSB_DrawThumb(LPSKINSB psb, HDC hdc, BOOL fVert, UINT uState) { SBCALC sbc; RECT rc, rect; HDC hSrcDC; HDC memDC; HBITMAP hOldBmp; HBITMAP hMemBitmap, hOldBitmap; int cx, cy; int xOffset, yOffset; int xOffset1, yOffset1; SkinSB_SBCalc(psb, &sbc, fVert); GetWindowRect(psb->hwnd, &rect); // Chack scrollbar of size whether valid if( (sbc.pxTop >= sbc.pxBottom) || (sbc.pxLeft >= sbc.pxRight) ) return ; // Draw the groove only if( (sbc.pxDownArrow - sbc.pxUpArrow) < (sbc.pxThumbBottom - sbc.pxThumbTop) || uState == SB_STATE_DISABLED ) { SkinSB_GetGrooveRect(psb, &rc, fVert); SkinSB_DrawGroove(psb, hdc, &rc, fVert); return ; } // Padding the groove part if( sbc.pxUpArrow < sbc.pxThumbTop ) { if( fVert ) SetRect(&rc, sbc.pxLeft, sbc.pxUpArrow, sbc.pxRight, sbc.pxThumbTop); else SetRect(&rc, sbc.pxUpArrow, sbc.pxTop, sbc.pxThumbTop, sbc.pxBottom); OffsetRect(&rc, -rect.left, -rect.top); SkinSB_DrawGroove(psb, hdc, &rc, fVert); } if( sbc.pxThumbBottom < sbc.pxDownArrow ) { if( fVert ) SetRect(&rc, sbc.pxLeft, sbc.pxThumbBottom, sbc.pxRight, sbc.pxDownArrow); else SetRect(&rc, sbc.pxThumbBottom, sbc.pxTop, sbc.pxDownArrow, sbc.pxBottom); OffsetRect(&rc, -rect.left, -rect.top); SkinSB_DrawGroove(psb, hdc, &rc, fVert); } // Draw the thumb use memory dc // Select scrollbar bitmap resource to dc hSrcDC = CreateCompatibleDC(hdc); hOldBmp = (HBITMAP)SelectObject(hSrcDC, psb->hBmp); // get the thumb rectangle SkinSB_GetThumbRect(psb, &rc, fVert); cx = rc.right - rc.left; cy = rc.bottom - rc.top; RECT rcMemDC = {0, 0, rc.right-rc.left, rc.bottom-rc.top}; // Create memory DC memDC = CreateCompatibleDC(hdc); hMemBitmap = CreateCompatibleBitmap(hdc, cx, cy); hOldBitmap = (HBITMAP)SelectObject(memDC, hMemBitmap); SetBkColor(memDC, RGB(255,255,255)); ExtTextOut(memDC, 0, 0, ETO_OPAQUE, &rcMemDC, NULL, 0, NULL); // Select state bitmap part xOffset = 16 * (uState + 8); yOffset = (fVert ? 0 : 16); xOffset1 = 16 * (uState + 11); yOffset1 = (fVert ? 0 : 16); if ( fVert ) { for( int i = 4; i < cy - 4; i += 8 ) BitBlt(memDC, 0, i, cx, 8, hSrcDC, xOffset, yOffset + 4, SRCCOPY); BitBlt(memDC, 0, 0, cx, 4, hSrcDC, xOffset, yOffset, SRCCOPY); BitBlt(memDC, 0, cy - 4, cx, 4, hSrcDC, xOffset, (yOffset + 16) - 4, SRCCOPY); if( cy > 16 + 8 ) { int y = (cy - 16) / 2; BitBlt(memDC, 0, y, cx, 16, hSrcDC, xOffset1, yOffset1, SRCCOPY); } } else { for( int i = 4; i < cx - 4; i += 8 ) BitBlt(memDC, i, 0, 8, cy, hSrcDC, xOffset + 4, yOffset, SRCCOPY); BitBlt(memDC, 0, 0, 4, cy, hSrcDC, xOffset, yOffset, SRCCOPY); BitBlt(memDC, cx - 4, 0, 4, cy, hSrcDC, (xOffset + 16) - 4, yOffset, SRCCOPY); if( cx > 16 + 8 ) { int x = (cx - 16) / 2; BitBlt(memDC, x, 0, 16, cy, hSrcDC, xOffset1, yOffset1, SRCCOPY); } } BitBlt(hdc, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, memDC, 0,0, SRCCOPY); // Release the memory DC SelectObject(memDC, hOldBitmap); DeleteDC(memDC); DeleteObject(hMemBitmap); SelectObject(hSrcDC, hOldBmp); DeleteDC(hSrcDC); } //---------------------------------------------------------- // Name : SkinSB_HitTest() // Desc : HitTest scrollbar items //---------------------------------------------------------- DWORD SkinSB_HitTest(LPSKINSB psb, BOOL fVert, POINT pt) { SBCALC sbc; UINT disFlags; int x; SkinSB_SBCalc(psb, &sbc, fVert); if( pt.x < sbc.pxLeft || pt.y < sbc.pxTop || pt.x > sbc.pxRight || pt.y > sbc.pxBottom ) return HTSCROLL_NONE; disFlags = SkinSB_GetDisableFlags(psb, fVert); x = fVert ? pt.y : pt.x; if( x < sbc.pxUpArrow ) { if( (disFlags & ESB_DISABLE_BOTH) || (disFlags & ESB_DISABLE_LTUP) ) return HTSCROLL_NONE; else return HTSCROLL_LINEUP; } else if( (x > sbc.pxUpArrow) && (x < sbc.pxThumbTop) ) { if( (disFlags & ESB_DISABLE_BOTH) || (disFlags & ESB_DISABLE_LTUP) ) return HTSCROLL_NONE; else return HTSCROLL_PAGEUP; } else if( (x >= sbc.pxThumbTop && x <= sbc.pxThumbBottom) && (sbc.pxThumbTop > 0 && sbc.pxThumbBottom > sbc.pxThumbTop) ) { return HTSCROLL_THUMB; } else if( (x > sbc.pxThumbBottom) && (x < sbc.pxDownArrow) ) { if( disFlags & ESB_DISABLE_BOTH || disFlags & ESB_DISABLE_RTDN ) return HTSCROLL_NONE; else return HTSCROLL_PAGEDOWN; } else if( x >= sbc.pxDownArrow ) { if( (disFlags & ESB_DISABLE_BOTH) || (disFlags & ESB_DISABLE_RTDN) ) return HTSCROLL_NONE; else return HTSCROLL_LINEDOWN; } return HTSCROLL_NONE; } //---------------------------------------------------------- // Name : SkinSB_SBCalc() // Desc : Calc the scrollbar items position and size //---------------------------------------------------------- void SkinSB_SBCalc(LPSKINSB psb, LPSBCALC lpcalc, BOOL fVert) { assert(psb && lpcalc); if( psb == NULL || lpcalc == NULL ) return; RECT rcBar; // scrollbar rect int nRange; // range of scrollbar int nWorkingsize; // size of scrollbar working int nArrowsize; // size of the arrow button int nThumbsize; // size of the thumb int nStart; // start position of the thumb int nThumbpos; // current position of the thumb SCROLLINFO* psi; SkinSB_GetScrollBarRect(psb, fVert, &rcBar); lpcalc->pxLeft = rcBar.left; lpcalc->pxTop = rcBar.top; lpcalc->pxRight = rcBar.right; lpcalc->pxBottom = rcBar.bottom; if( fVert ) { psi = &psb->Vert; nArrowsize = SBMETRICS::cxVArrow; nWorkingsize = (rcBar.bottom - rcBar.top) - nArrowsize * 2; nStart = rcBar.top + nArrowsize; lpcalc->pxUpArrow = rcBar.top + nArrowsize; lpcalc->pxDownArrow = rcBar.bottom - nArrowsize; } else { psi = &psb->Horz; nArrowsize = SBMETRICS::cxHArrow; nWorkingsize = (rcBar.right - rcBar.left) - nArrowsize * 2; nStart = rcBar.left + nArrowsize; lpcalc->pxUpArrow = rcBar.left + nArrowsize; lpcalc->pxDownArrow = rcBar.right - nArrowsize; } nRange = (psi->nMax - psi->nMin) + 1; // Calculate size of the thumb if( SkinSB_IsScrollInfoActive(psi) ) { nThumbsize = MulDiv(psi->nPage, nWorkingsize, nRange); if( nThumbsize < MIN_THUMB_SIZE ) nThumbsize = MIN_THUMB_SIZE; int pagesize = max(1, psi->nPage); nThumbpos = MulDiv(psi->nPos - psi->nMin, nWorkingsize - nThumbsize, nRange - pagesize); if( nThumbpos < 0 ) nThumbpos = 0; if( nThumbpos >= nWorkingsize - nThumbsize ) nThumbpos = nWorkingsize - nThumbsize; nThumbpos += nStart; lpcalc->pxThumbTop = nThumbpos; lpcalc->pxThumbBottom = nThumbpos + nThumbsize; } else { lpcalc->pxThumbTop = 0; lpcalc->pxThumbBottom = 0; } } //--------------------------------------------------------- // Name : SkinSB_TrackThumb() // Desc : Track the scroll thumb //--------------------------------------------------------- BOOL SkinSB_TrackThumb(LPSKINSB psb, BOOL fVert, POINT pt) { SBCALC sbclc; int nPos; int nThumbpos; int nRange; int nThumbsize; int nWorksize; LPSCROLLINFO psi; SkinSB_SBCalc(psb, &sbclc, fVert); if( fVert ) { psi = &psb->Vert; nThumbpos = pt.y - psb->pxMouseOffset; } else { psi = &psb->Horz; nThumbpos = pt.x - psb->pxMouseOffset; } nPos = 0; nThumbpos -= sbclc.pxUpArrow; nThumbsize = sbclc.pxThumbBottom - sbclc.pxThumbTop; nWorksize = sbclc.pxDownArrow - sbclc.pxUpArrow; nRange = (psi->nMax - psi->nMin) + 1; if( nThumbpos < 0 ) nThumbpos = 0; if( nThumbpos > nWorksize - nThumbsize) nThumbpos = nWorksize - nThumbsize; if( nRange > 0 ) nPos = MulDiv(nThumbpos, nRange - psi->nPage, nWorksize - nThumbsize); // Send the scroll message to window !!! if( psi->nPos != nPos ) { psi->nTrackPos = nPos; psb->nTrackPos = nPos; // NOTE: 2008-12-24 // Not use the SB_THUMBTRACK flag that because of // the RichEdit cannot receving the WM_MOUSEMOVE message if( psb->fRichEdit ) DoScrollMsg(psb->hwnd, /*SB_THUMBTRACK*/SB_THUMBPOSITION, nPos, fVert); else DoScrollMsg(psb->hwnd, SB_THUMBTRACK, nPos, fVert); } return TRUE; } //--------------------------------------------------------- // Name : SkinSB_GetState() // Desc : Get scrollbar item status //--------------------------------------------------------- UINT SkinSB_GetState(LPSKINSB psb, BOOL fVert, UINT nHitItem) { BOOL fHotTracked; BOOL fPressed; BOOL fDisabled; UINT disFlags; UINT uState; fHotTracked = fPressed = fDisabled = FALSE; disFlags = SkinSB_GetDisableFlags(psb, fVert); switch( nHitItem ) { case HTSCROLL_LINEUP: fDisabled = ((disFlags & ESB_DISABLE_BOTH) || (disFlags & ESB_DISABLE_UP)); break; case HTSCROLL_LINEDOWN: fDisabled = ((disFlags & ESB_DISABLE_BOTH) || (disFlags & ESB_DISABLE_DOWN)); break; case HTSCROLL_THUMB: fDisabled = (disFlags & ESB_DISABLE_BOTH); break; case HTSCROLL_PAGEUP: case HTSCROLL_PAGEDOWN: case HTSCROLL_SIZEBOX: case HTSCROLL_NONE: return 0; } if( (nHitItem == GET_HTITEM(psb->dwLastCode)) && fVert == (HTSCROLL_VERT == GET_HTVERT(psb->dwLastCode)) ) fHotTracked = TRUE; if( !fDisabled && psb->fTracking && fHotTracked ) fPressed = TRUE; if( fDisabled ) uState = SB_STATE_DISABLED; else if( fPressed ) uState = SB_STATE_SELECTED; else if( fHotTracked ) uState = SB_STATE_HIGHLIGHT; else uState = SB_STATE_DEFAULT; return uState; } //---------------------------------------------------------- // Name : SkinSB_Track() // Desc : //---------------------------------------------------------- void SkinSB_Track(LPSKINSB psb, DWORD dwTrackCode, POINT pt) { LPSCROLLINFO psi; WORD wSBCode; DWORD dwTrackItem; BOOL fTrackVert; dwTrackItem = GET_HTITEM(dwTrackCode); fTrackVert = GET_HTVERT(dwTrackCode); psi = (fTrackVert ? &psb->Vert : &psb->Horz); switch( dwTrackItem ) { case HTSCROLL_THUMB: SBCALC sbclc; SkinSB_SBCalc(psb, &sbclc, fTrackVert); psi->nTrackPos = psi->nPos; psb->pxMouseOffset = (fTrackVert ? pt.y : pt.x) - sbclc.pxThumbTop; break; case HTSCROLL_LINEUP: wSBCode = SB_LINEUP; goto DoScroll; case HTSCROLL_LINEDOWN: wSBCode = SB_LINEDOWN; goto DoScroll; case HTSCROLL_PAGEDOWN: wSBCode = SB_PAGEDOWN; goto DoScroll; case HTSCROLL_PAGEUP: wSBCode = SB_PAGEUP; DoScroll: psb->nScrollTimerMsg = MAKELONG((fTrackVert ? WM_VSCROLL : WM_HSCROLL), wSBCode); DoScrollMsg(psb->hwnd, wSBCode, 0, fTrackVert); SetTimer(psb->hwnd, ID_TIMER_DELAY, TIME_SCROLL_DELAY, NULL); break; default: return; } psb->dwTrackCode = dwTrackCode; psb->fTracking = TRUE; SkinSB_HotTrack(psb, psb->dwTrackCode, TRUE); SetCapture(psb->hwnd); //SkinSB_TrackLoop(psb); } /* //---------------------------------------------------------- // Name : SkinSB_TrackLoop() // Desc : //---------------------------------------------------------- void SkinSB_TrackLoop(LPSKINSB psb) { HWND hwnd; MSG msg; int cmd; //POINT pt; if( !psb->fTracking ) return; hwnd = psb->hwnd; while( GetCapture() == hwnd ) { if( !GetMessage(&msg, hwnd, 0, 0) ) break; if( !CallMsgFilter(&msg, MSGF_SCROLLBAR) ) { cmd = msg.message; if( msg.hwnd == hwnd && ((cmd >= WM_MOUSEFIRST && cmd <= WM_MOUSELAST) || (cmd >= WM_KEYFIRST && cmd <= WM_KEYLAST)) ) { TRACE("message loop\n"); SkinSB_Proc(hwnd, cmd, msg.wParam, msg.lParam); } } else { TranslateMessage(&msg); DispatchMessage(&msg); } } }*/ //---------------------------------------------------------- // Name : SkinSB_HotTrack() // Desc : Hot scrollbar arrow and thumb items //---------------------------------------------------------- BOOL SkinSB_HotTrack(LPSKINSB psb, DWORD dwTrackCode, BOOL fMouseDown) { HDC hdc; DWORD dwOldCode; DWORD dwHitItem; BOOL fVert; // Save old hittest code dwOldCode = psb->dwLastCode; psb->dwLastCode = dwTrackCode; dwHitItem = GET_HTITEM(dwTrackCode); fVert = GET_HTVERT(dwTrackCode); hdc = GetWindowDC(psb->hwnd); if( dwTrackCode != dwOldCode || fMouseDown) { // Restore old scrollbar item state if( GET_HTITEM(dwOldCode) == HTSCROLL_LINEUP ) SkinSB_DrawArrow(psb, hdc, GET_HTVERT(dwOldCode), HTSCROLL_LINEUP, SB_STATE_DEFAULT); else if( GET_HTITEM(dwOldCode) == HTSCROLL_LINEDOWN ) SkinSB_DrawArrow(psb, hdc, GET_HTVERT(dwOldCode), HTSCROLL_LINEDOWN, SB_STATE_DEFAULT); else if( GET_HTITEM(dwOldCode) == HTSCROLL_THUMB ) SkinSB_DrawThumb(psb, hdc, GET_HTVERT(dwOldCode), SB_STATE_DEFAULT); // Draw new scrollbar item state if( dwHitItem == HTSCROLL_LINEUP ) SkinSB_DrawArrow(psb, hdc, fVert, HTSCROLL_LINEUP, fMouseDown ? SB_STATE_SELECTED : SB_STATE_HIGHLIGHT); else if( dwHitItem == HTSCROLL_LINEDOWN ) SkinSB_DrawArrow(psb, hdc, fVert, HTSCROLL_LINEDOWN, fMouseDown ? SB_STATE_SELECTED : SB_STATE_HIGHLIGHT); else if( dwHitItem == HTSCROLL_THUMB) SkinSB_DrawThumb(psb, hdc, fVert, fMouseDown ? SB_STATE_SELECTED : SB_STATE_HIGHLIGHT); } ReleaseDC(psb->hwnd, hdc); return TRUE; } // Message handle //---------------------------------------------------------- // Name : SkinSB_OnStyleChanged() // Desc : //---------------------------------------------------------- LRESULT SkinSB_OnStyleChanged(LPSKINSB psb, int nStyleType, LPSTYLESTRUCT lpStyleStruct) { if( psb->fPreventStyleChange ) return 0; if( nStyleType == GWL_EXSTYLE ) { BOOL fOld = psb->fLeftScrollBar; if( lpStyleStruct->styleNew & WS_EX_LEFTSCROLLBAR ) psb->fLeftScrollBar = TRUE; else psb->fLeftScrollBar = FALSE; if( fOld != psb->fLeftScrollBar ) RedrawFrame(psb->hwnd); } return CallWindowProc(psb->pfnOldProc, psb->hwnd, WM_STYLECHANGED, nStyleType, (LPARAM)lpStyleStruct); } //---------------------------------------------------------- // Name : SkinSB_OnNcCalcSize() // Desc : //---------------------------------------------------------- LRESULT SkinSB_OnNcCalcSize(LPSKINSB psb, BOOL bCalcValidRects, NCCALCSIZE_PARAMS* lpncsp) { LRESULT lr; DWORD dwStyle; RECT* lprc, rect; lprc = &lpncsp->rgrc[0]; rect = *lprc; dwStyle = GetWindowLong(psb->hwnd, GWL_STYLE); if( dwStyle & (WS_VSCROLL | WS_HSCROLL) ) { psb->fPreventStyleChange = TRUE; SetWindowLong(psb->hwnd, GWL_STYLE, dwStyle & ~(WS_VSCROLL|WS_HSCROLL)); } lr = CallWindowProc(psb->pfnOldProc, psb->hwnd, WM_NCCALCSIZE, (WPARAM)bCalcValidRects, (LPARAM)lpncsp); if( dwStyle & (WS_VSCROLL | WS_HSCROLL) ) { SetWindowLong(psb->hwnd, GWL_STYLE, dwStyle); psb->fPreventStyleChange = FALSE; } if( (dwStyle & WS_HSCROLL) && (lprc->bottom - lprc->top) > SBMETRICS::cxHArrow ) { lprc->bottom -= SBMETRICS::cxHArrow; } if( (dwStyle & WS_VSCROLL) && (lprc->right - lprc->left) > SBMETRICS::cxVArrow ) { if( psb->fLeftScrollBar ) lprc->left += SBMETRICS::cxVArrow; else lprc->right -= SBMETRICS::cxVArrow; } return lr; } //---------------------------------------------------------- // Name : SkinSB_OnNcPaint() // Desc : //---------------------------------------------------------- LRESULT SkinSB_OnNcPaint(LPSKINSB psb, HRGN hRgn) { LRESULT lr; DWORD dwStyle; HDC hDC; if( !IsWindowVisible(psb->hwnd) ) return 0; dwStyle = GetWindowLong(psb->hwnd, GWL_STYLE); if( dwStyle & (WS_VSCROLL | WS_HSCROLL) ) { psb->fPreventStyleChange = TRUE; SetWindowLong(psb->hwnd, GWL_STYLE, dwStyle & ~(WS_VSCROLL|WS_HSCROLL)); } // draw frame border by system lr = CallWindowProc(psb->pfnOldProc, psb->hwnd, WM_NCPAINT, (WPARAM)hRgn, 0); if( dwStyle & (WS_VSCROLL | WS_HSCROLL) ) { SetWindowLong(psb->hwnd, GWL_STYLE, dwStyle); psb->fPreventStyleChange = FALSE; } //hDC = GetDCEx(psb->hwnd, hRgn, DCX_WINDOW|DCX_INTERSECTRGN|DCX_CACHE ); hDC = GetWindowDC(psb->hwnd); // Draw scrollbar if( dwStyle & WS_VSCROLL ) SkinSB_DrawScrollBar(psb, hDC, TRUE); if( dwStyle & WS_HSCROLL ) SkinSB_DrawScrollBar(psb, hDC, FALSE); // draw the size box if( dwStyle & (WS_VSCROLL | WS_HSCROLL) ) SkinSB_DrawSizeBox(psb, hDC); ReleaseDC(psb->hwnd, hDC); return lr; } //---------------------------------------------------------- // Name : SkinSB_OnNcHitTest() // Desc : //---------------------------------------------------------- LRESULT SkinSB_OnNcHitTest(LPSKINSB psb, WPARAM wParam, LPARAM lParam) { RECT rcHorz, rcVert, rcSize; POINT pt = {LOWORD(lParam), HIWORD(lParam)}; SkinSB_GetScrollBarRect(psb, TRUE, &rcVert); SkinSB_GetScrollBarRect(psb, FALSE, &rcHorz); SkinSB_GetSizeBoxRect(psb, &rcSize); if( PtInRect(&rcVert, pt) ) return HTVSCROLL; else if( PtInRect(&rcHorz, pt) ) return HTHSCROLL; else if( PtInRect(&rcSize, pt) ) return HTSIZE; return CallWindowProc(psb->pfnOldProc, psb->hwnd, WM_NCHITTEST, wParam, lParam); } //---------------------------------------------------------- // Name : SkinSB_OnNcMouseMove() // Desc : //---------------------------------------------------------- LRESULT SkinSB_OnNcMouseMove(LPSKINSB psb, WPARAM wParam, LPARAM lParam) { if( wParam == HTHSCROLL || wParam == HTVSCROLL ) { POINT pt; BOOL fVert; DWORD dwHitCode; pt.x = LOWORD(lParam); pt.y = HIWORD(lParam); fVert = ( wParam == HTVSCROLL ); if( !SkinSB_IsScrollInfoActive((fVert ? &psb->Vert : &psb->Horz)) ) return 0; dwHitCode = SkinSB_HitTest(psb, fVert, pt); if( dwHitCode == HTSCROLL_NONE ) return 0; if( fVert ) dwHitCode |= HTSCROLL_VERT; SkinSB_HotTrack(psb, dwHitCode, FALSE); } else if( wParam == HTSIZE ) { SkinSB_HotTrack(psb, HTSCROLL_NONE, FALSE); } return CallWindowProc(psb->pfnOldProc, psb->hwnd, WM_NCMOUSEMOVE, wParam, lParam); } //--------------------------------------------------------- // Name : SkinSB_OnNcMouseLeave() // Desc : //--------------------------------------------------------- LRESULT SkinSB_OnNcMouseLeave(LPSKINSB psb, WPARAM wParam, LPARAM lParam) { UNREFERENCED_PARAMETER(wParam); UNREFERENCED_PARAMETER(lParam); psb->fMouseTracking = FALSE; if( psb->fTracking ) return 0; SkinSB_HotTrack(psb, HTSCROLL_NONE, FALSE); psb->dwLastCode = HTSCROLL_NONE; return 0; } //---------------------------------------------------------- // Name : SkinSB_OnNcLButtonDown() // Desc : //---------------------------------------------------------- LRESULT SkinSB_OnNcLButtonDown(LPSKINSB psb, WPARAM wParam, LPARAM lParam) { if( wParam == HTHSCROLL || wParam == HTVSCROLL ) { POINT pt; BOOL fVert; DWORD dwHitCode; LPSCROLLINFO psi; pt.x = LOWORD(lParam); pt.y = HIWORD(lParam); fVert = (wParam == HTVSCROLL); psi = (fVert ? &psb->Vert : &psb->Horz); if( !SkinSB_IsScrollInfoActive(psi) ) return 0; dwHitCode = SkinSB_HitTest(psb, fVert, pt); if( dwHitCode == HTSCROLL_NONE ) return 0; if( fVert ) dwHitCode |= HTSCROLL_VERT; psb->nTrackPos = psi->nPos; psb->dwLastCode = dwHitCode; SkinSB_Track(psb, dwHitCode, pt); return 0; } return CallWindowProc(psb->pfnOldProc, psb->hwnd, WM_NCLBUTTONDOWN, wParam, lParam); } //---------------------------------------------------------- // Name : SkinSB_OnMouseMove() // Desc : //---------------------------------------------------------- LRESULT SkinSB_OnMouseMove(LPSKINSB psb, WPARAM wParam, LPARAM lParam) { DWORD dwPos; POINT pt; dwPos = GetMessagePos(); pt.x = LOWORD(dwPos); pt.y = HIWORD(dwPos); // Mouse left button down if( psb->fTracking && (wParam & MK_LBUTTON) ) { if( GET_HTITEM(psb->dwTrackCode) == HTSCROLL_THUMB ) { SkinSB_TrackThumb(psb, GET_HTVERT(psb->dwTrackCode), pt); return 0; } LRESULT lr = SkinSB_OnNcHitTest(psb, 0, dwPos); if( lr == HTHSCROLL || lr == HTVSCROLL ) { BOOL fVert = (lr == HTVSCROLL); DWORD dwHitCode = SkinSB_HitTest(psb, fVert, pt); if( fVert ) dwHitCode |= HTSCROLL_VERT; if( dwHitCode != psb->dwTrackCode ) // Unallowed hot-track other hittest item SkinSB_HotTrack(psb, HTSCROLL_NONE, FALSE); else SkinSB_HotTrack(psb, psb->dwTrackCode, TRUE); } else { SkinSB_HotTrack(psb, HTSCROLL_NONE, FALSE); } return 0; } return CallWindowProc(psb->pfnOldProc, psb->hwnd, WM_MOUSEMOVE, wParam, lParam); } //---------------------------------------------------------- // Name : SkinSB_OnLButtonUp() // Desc : //---------------------------------------------------------- LRESULT SkinSB_OnLButtonUp(LPSKINSB psb, WPARAM wParam, LPARAM lParam) { DWORD dwHitItem = GET_HTITEM(psb->dwTrackCode); BOOL fTrackVert = GET_HTVERT(psb->dwTrackCode); if( dwHitItem != HTSCROLL_NONE && psb->fTracking) { // Release mouse capture ReleaseCapture(); // End scroll switch( dwHitItem ) { case HTSCROLL_LINEUP: case HTSCROLL_LINEDOWN: case HTSCROLL_PAGEUP: case HTSCROLL_PAGEDOWN: KillTimer(psb->hwnd, ID_TIMER_SCROLL); DoScrollMsg(psb->hwnd, SB_ENDSCROLL, 0, fTrackVert); break; case HTSCROLL_THUMB: if( psb->fTracking ) { DWORD dwPos; DWORD dwCode; POINT pt; dwPos = GetMessagePos(); pt.x = LOWORD(dwPos); pt.y = HIWORD(dwPos); DoScrollMsg(psb->hwnd, SB_THUMBPOSITION, psb->nTrackPos, fTrackVert); DoScrollMsg(psb->hwnd, SB_ENDSCROLL, 0, fTrackVert); dwCode = SkinSB_HitTest(psb, fTrackVert, pt); if( fTrackVert ) dwCode |= HTSCROLL_VERT; psb->dwLastCode = dwCode; } break; } // Clean the track parameters psb->pxMouseOffset = 0; psb->nScrollTimerMsg = MAKELONG(WM_NULL, 0); psb->dwTrackCode = HTSCROLL_NONE; psb->fTracking = FALSE; //psb->nTrackPos = 0; HDC hdc = GetWindowDC(psb->hwnd); SkinSB_DrawScrollBar(psb, hdc, fTrackVert); ReleaseDC(psb->hwnd, hdc); return 0; } return CallWindowProc(psb->pfnOldProc, psb->hwnd, WM_LBUTTONUP, wParam, lParam); } //---------------------------------------------------------- // Name : SkinSB_OnTimer() // Desc : //---------------------------------------------------------- LRESULT SkinSB_OnTimer(LPSKINSB psb, WPARAM wParam, LPARAM lParam) { DWORD dwHitItem = GET_HTITEM(psb->dwTrackCode); BOOL fTrackVert = GET_HTVERT(psb->dwTrackCode); if( wParam == ID_TIMER_SCROLL ) { // if mouse left button released then close scroll timer if( dwHitItem == HTSCROLL_NONE ) { KillTimer(psb->hwnd, ID_TIMER_SCROLL); return 0; } // Timer send scroll message if( psb->dwTrackCode == psb->dwLastCode ) { WORD wSBCode = HIWORD(psb->nScrollTimerMsg); if( wSBCode == SB_PAGEDOWN || wSBCode == SB_PAGEUP ) { SBCALC sbc; DWORD dwPos; POINT pt; int px; dwPos = GetMessagePos(); pt.x = LOWORD(dwPos); pt.y = HIWORD(dwPos); SkinSB_SBCalc(psb, &sbc, fTrackVert); px = (fTrackVert ? pt.y : pt.x); if( wSBCode == SB_PAGEDOWN ) { if( sbc.pxThumbBottom >= px ) { KillTimer(psb->hwnd, ID_TIMER_SCROLL); return 0; } } else { if( sbc.pxThumbTop <= px ) { KillTimer(psb->hwnd, ID_TIMER_SCROLL); return 0; } } } DoScrollMsg(psb->hwnd, wSBCode, 0, fTrackVert); } return 0; } else if(wParam == ID_TIMER_DELAY) { KillTimer(psb->hwnd, ID_TIMER_DELAY); SetTimer(psb->hwnd, ID_TIMER_SCROLL, TIME_SCROLL_INTERVAL, 0); return 0; } return CallWindowProc(psb->pfnOldProc, psb->hwnd, WM_TIMER, wParam, lParam); } //---------------------------------------------------------- // Name : SkinSB_Proc() // Desc : //---------------------------------------------------------- LRESULT CALLBACK SkinSB_Proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { LPSKINSB psb = SkinSB_GetSB(hwnd); if( psb && uMsg == WM_NCMOUSEMOVE ) { if(!psb->fMouseTracking && !psb->fTracking) { TRACKMOUSEEVENT tme; tme.cbSize = sizeof(tme); tme.hwndTrack = psb->hwnd; tme.dwFlags = TME_LEAVE|TME_NONCLIENT; tme.dwHoverTime = 0; psb->fMouseTracking = _TrackMouseEvent(&tme); } } switch( uMsg ) { case WM_NCPAINT: return SkinSB_OnNcPaint(psb, (HRGN)wParam); case WM_NCCALCSIZE: return SkinSB_OnNcCalcSize(psb, (BOOL)wParam, (NCCALCSIZE_PARAMS*)lParam); case WM_NCHITTEST: return SkinSB_OnNcHitTest(psb, wParam, lParam); case WM_STYLECHANGED: return SkinSB_OnStyleChanged(psb, (int)wParam, (LPSTYLESTRUCT)lParam); case WM_NCLBUTTONDOWN: return SkinSB_OnNcLButtonDown(psb, wParam, lParam); case WM_NCMOUSEMOVE: return SkinSB_OnNcMouseMove(psb, wParam, lParam); case WM_MOUSEMOVE: return SkinSB_OnMouseMove(psb, wParam, lParam); case WM_LBUTTONUP: return SkinSB_OnLButtonUp(psb, wParam, lParam); case WM_NCMOUSELEAVE: return SkinSB_OnNcMouseLeave(psb, wParam, lParam); case WM_NCLBUTTONDBLCLK: case WM_NCRBUTTONDBLCLK: return 0; case WM_TIMER: return SkinSB_OnTimer(psb, wParam, lParam); case WM_NCDESTROY: { LRESULT lr = CallWindowProc(psb->pfnOldProc, hwnd, uMsg, wParam, lParam); SkinSB_Uninit(hwnd); return lr; } } return CallWindowProc(psb->pfnOldProc, hwnd, uMsg, wParam, lParam); }